package main

import "fmt"

const SIZE = 5

func testPointer() {
	i := 1
	var iPtr1 *int = &i
	fmt.Println("[func|testPointer]iPtr1=", iPtr1, "iPtr1 value=", *iPtr1)

	iPtr2 := &i
	fmt.Println("[func|testPointer]iPtr2=", iPtr2, "iPtr2 value=", *iPtr2)

	var iPtr3 *int
	iPtr3 = &i
	fmt.Println("[func|testPointer]iPtr3=", iPtr3, "iPtr3 value=", *iPtr3)

	var iPtr4 = &i
	fmt.Println("[func|testPointer]iPtr4=", iPtr4, "iPtr4 value=", *iPtr4)

	var iPtr5 *int
	fmt.Println("[func|testPointer]iPtr5=", iPtr5, "iPtr5 == nil", iPtr5 == nil)
}

func testPointerArray() {
	var pointerArray [SIZE]*int
	var array [SIZE]int = [SIZE]int{1, 2, 3, 4, 5}

	for i := 0; i < SIZE; i++ {
		pointerArray[i] = &array[i]
	}
	fmt.Println("[func|testPointerArray]pointerArray=", pointerArray)

	fmt.Println()

	for i := 0; i < SIZE; i++ {
		fmt.Printf("[func|testPointerArray]pointerArray[%d]=%d\n", i, *pointerArray[i])
	}
}

func testPointerToPointer() {
	i := 1
	var iPtr1 *int = &i
	fmt.Println("[func|testPointerToPointer]iPtr1=", iPtr1, "iPtr1 value=", *iPtr1)

	var iPtr2 **int = &iPtr1
	fmt.Println("[func|testPointerToPointer]iPtr2=", iPtr2, "iPtr2 value=", **iPtr2)

	var iPtr3 ***int = &iPtr2
	fmt.Println("[func|testPointerToPointer]iPtr3=", iPtr3, "iPtr3 value=", ***iPtr3)

	var iPtr4 ****int = &iPtr3
	fmt.Println("[func|testPointerToPointer]iPtr4=", iPtr4, "iPtr4 value=", ****iPtr4)
}

func testSwap1(a, b *int) {
	*a, *b = *b, *a
	fmt.Println("[func|testSwap1]a=", *a, "b=", *b)
}

func testSwap2(a, b *int) {
	a, b = b, a
	fmt.Println("[func|testSwap1]a=", *a, "b=", *b)
}

func main() {
	testPointer()
	fmt.Println()
	testPointerArray()
	fmt.Println()
	testPointerToPointer()
	fmt.Println()
	a, b := 1, 2
	testSwap1(&a, &b)
	fmt.Println("[func|main call testSwap1]a=", a, "b=", b)
	fmt.Println()
	x, y := 3, 4
	testSwap2(&x, &y)
	fmt.Println("[func|main call testSwap2]x=", x, "b=", y)
}
